package edu.dillo.dillotude;

import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

import org.newdawn.slick.Animation;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.state.StateBasedGame;

public class InteractiveObject {
	
	protected HashMap<String, Animation> Animations;
	protected float X;
	protected float Y;
	protected float Radius;
	protected Vector2f Velocity;
	protected Vector2f Acceleration;
	private String activeAnimationKey;
	protected Animation activeAnimation;
	protected enum dir {TOP, DOWN, LEFT, RIGHT, NONE};
	private int elaspedTime;

	public InteractiveObject(float x, float y, float r)
	{
		setX(x);
		setY(y);
		setRadius(r);
		setVelocity(new Vector2f(0,0));
		setAcceleration(new Vector2f(0,0));
		Animations = new HashMap<String, Animation>();
		
	}
	public void init(GameContainer arg0, StateBasedGame arg1)
			throws SlickException {
		activeAnimation = Animations.get(0);
		activeAnimation.start();
		
	}
	public void update(GameContainer arg0, StateBasedGame arg1, int arg2)
			throws SlickException {
		activeAnimation.update(0);
		Velocity.set(Velocity.x+Acceleration.x, Velocity.y+Acceleration.y);
		X += Velocity.x;
		Y += Velocity.y; 
		
	}
	public boolean TouchingBlock(GridBlock GrBl)
	{
		
		int xr, xl, yr, yl, gxr, gxl, gyr, gyl;
		boolean inbY, inbX;
		
		xr = (int) (X + (3*Radius)/4);
		xl = (int) (X + Radius/4);
		yr = (int) (Y);
		yl = (int) (Y + Radius);
		// these represent the farthest X and Y points
		// I added to the X points to make the hitbox smaller
		
		gxr = (int) GrBl.getMaxX();
		gxl = (int) GrBl.getMinX();
		gyr = (int) GrBl.getMinY();
		gyl = (int) GrBl.getMaxY();
		// this does the same thing but with the box
		
		inbX = ((xr <= gxr && xr >= gxl) || (gxr <= xl && gxr >= xr) || (xr >= gxr && xr <= gxl) || (gxr >= xl && gxr <= xr));
		inbY = ((yr <= gyr && yr >= gyl) || (gyr >= yl && gyr <= yr) || (yr >= gyr && yr <= gyl) || (gyr <= yl && gyr >= yr));
		// this test if the x and y range are within eachother in any way
		// if both the x and y range coincide with eachother, that means it is hittesting
		if (!GrBl.isCollidable())
			return false;
		else return (inbX && inbY);
		
		// this returns if both the x and y are true, if either is false this function returns false
	}
	public dir WhichSideofBlock(GridBlock GrBl)
	{
		int por_y = (int) (Y + Radius);
		int por_x = (int) (X + Radius/2);
		int centerx = (int) GrBl.getCenterX();
		int centery = (int) GrBl.getCenterY();
		int diffx = centerx - por_x;
		int diffy = centery - por_y;
		// first I set a point of reference on the player object
		// I chose the center bottom, so where his feet are
		// diffy and diffx are the difference in x and y
		
		if(diffy >= 0 && diffx > -70 && diffx < 70)
		{
			return dir.TOP;
			// if the difference in y is positive it is touching the top
			// the diffx stuff is just to make the top of the block less wide
		}
		else if(diffy < 0 - Radius && diffx > -70 && diffx < 70)
		{
			return dir.DOWN;
		}
		else if(diffx <= 0 && diffy < 40 && diffy > (-20 - Radius))
		{
			return dir.RIGHT;
		}
		else if(diffx > 0 && diffy < 40)
		{
			return dir.LEFT;
		}	
		
		// same deal here, I might shrink the RIGHT and LEFT area later but I need to have a few blocks placed around, and an array of blocks to do that
		// these number can just be tinkered with just to change the hitbox size of the different sides of the box
	
		return dir.NONE;
	}
	public void pushback(dir direction, GridBlock GrBl)
	{
		switch (direction)
		{
		case TOP:
			Y = GrBl.getY() - Radius + 1;
			Velocity.y = 0;
			break;
		case LEFT:
			X = GrBl.getX() - (int)(3*Radius/4)-1;
			Velocity.x = 0;
			break;
		case RIGHT:
			X  = GrBl.getX() + 50;
			Velocity.x = 0;
			break;
		case DOWN:
			Y = GrBl.getY() + 100;
			Velocity.y = 0;
			break;
		default:
			break;
		}
		// if he is touching the top he just gets pushed back to the top of the box
		// more if statements can be added later for the different sides
	}
	public boolean checkCollisionWith(InteractiveObject obj)
	{
		double distance = Math.sqrt(Math.pow(X + obj.getX(), 2) + Math.pow(Y + obj.getY(), 2));
		
		return (distance <= (Radius+obj.getRadius()))?true:false;
	}
	
	public boolean checkCollisionWith(GridBlock block)
	{
		return false;
	}
	
	public String getActiveAnimationKey()
	{
		return activeAnimationKey;
	}
	
	public void setActiveAnimationKey(String key)
	{
		activeAnimationKey = key;
		activeAnimation = Animations.get(activeAnimationKey);
	}
	
	public Animation getActiveAnimation()
	{
		return activeAnimation;
	}
	
	public void addAnimation(String animdir, Dimension[] animdims, Dimension[] framedims,int[] animspeeds, int[] lastrowlengths, String[] animnames) throws SlickException
	{
		try {
			System.out.println(new File(".").getCanonicalPath());
		} catch (IOException e) {
			e.printStackTrace();
		}
		 File animDir = new File(animdir);
		 try {
			animDir = animDir.getCanonicalFile();
		} catch (IOException e) {
			e.printStackTrace();
		}
		 
		 if (animDir.isDirectory())
		 {
			 File[] animFiles = animDir.listFiles();
			 int numFiles = animFiles.length;
			 if (animdims.length != numFiles || framedims.length != numFiles || lastrowlengths.length != numFiles || animnames.length != numFiles)
			 {
				 System.out.println("The size of the arrays do not match the number of files in the directory.  Wow.");
			 }
			 else
			 {
				 for (int i = 0; i < numFiles; i++)
				 {
					 SpriteSheet sheet = new SpriteSheet(animFiles[i].getAbsolutePath(), animdims[i].width, animdims[i].height);
					 Animations.put(animnames[i], new Animation());
					 Animations.put(animnames[i] + "-flipped", new Animation());
					 for(int row = 0; row < framedims[i].height; row++)
					 {
						 if (row < framedims[i].height-1)
						 {
			                 for(int col = 0; col < framedims[i].width; col++)
			                 {
			                         Animations.get(animnames[i]).addFrame(sheet.getSprite(col, row), animspeeds[i]);
			                         Animations.get(animnames[i] + "-flipped").addFrame(sheet.getSprite(col, row).getFlippedCopy(true, false),animspeeds[i]);
			                 }
						 }
						 else
						 {
							 for(int col = 0; col < lastrowlengths[i]; col++)
			                 {
			                         Animations.get(animnames[i]).addFrame(sheet.getSprite(col, row), animspeeds[i]);
			                         Animations.get(animnames[i] + "-flipped").addFrame(sheet.getSprite(col, row).getFlippedCopy(true, false), animspeeds[i]);
			                 }
						 }
			         }
					 Animations.get(animnames[i]).setAutoUpdate(true);
				 }
			 } 
		 }
		 else
		 {
			 System.out.println("Oops, the animation directory wasn't a directory. Oh darn.");
		 }
		 
	}

	public float getY() {
		return Y;
	}

	public void setY(float y) {
		Y = y;
	}

	public float getX() {
		return X;
	}

	public void setX(float x) {
		X = x;
	}

	public float getRadius() {
		return Radius;
	}

	public void setRadius(float radius) {
		Radius = radius;
	}

	public Vector2f getVelocity() {
		return Velocity;
	}

	public void setVelocity(Vector2f velocity) {
		Velocity = velocity;
	}

	public Vector2f getAcceleration() {
		return Acceleration;
	}

	public void setAcceleration(Vector2f acceleration) {
		Acceleration = acceleration;
	}

	public void render(GameContainer arg0, Graphics g) throws SlickException {
		// TODO Auto-generated method stub
		
	}
}
